home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 06 - 1990 / 06.04 Apr 90 / List Demo Project / List Utilities < prev    next >
Encoding:
Text File  |  1989-08-02  |  22.5 KB  |  737 lines  |  [TEXT/PJMM]

  1. unit ListUtilities;
  2. interface
  3.     uses
  4.         KeyBoard, Memory, Sane, StringUtilities;
  5.     type
  6.         ListGlobalType = record
  7.                 window: WindowPtr;{the window which owns the list}
  8.                 nListItem: integer;{item number in the dialog}
  9.                 Box: rect;{box of the entire list including the scroll bars}
  10.                 List: ListHandle;
  11.  
  12.                 selCell: cell;{cell corresponding to the TE record}
  13.                 multiple: boolean;{is more than one cell selected?}
  14.                 TEexists: boolean;
  15.                 hTE: TEHandle;
  16.                 TErect: rect;
  17.                 largeTERect: boolean;
  18.  
  19.                 doubleClick: boolean;
  20.  
  21.                 Editable: packed array[0..30] of boolean;{is that column editable?}
  22.                 Number: packed array[0..30] of boolean; {these specify which columns are numbers and which contain general text}
  23.                 Integer: packed array[0..30] of boolean; {furthermore, should the column be restricted to integer quantities}
  24.             end;
  25.         ListGlobalPtr = ^ListGlobalType;
  26.         ListGlobalHandle = ^ListGlobalPtr;
  27.     function ListFilterProc (Dlg: WindowPtr;
  28.                                     var theEvent: EventRecord;
  29.                                     var ItemHit: integer): boolean;
  30.     procedure SetUpListItem (Dlg: DialogPtr;
  31.                                     nListItem: integer;
  32.                                     var ListGlobal: ListGlobalHandle;
  33.                                     cols, rows: integer);
  34.     procedure SetUpList (w: WindowPtr;
  35.                                     var ListGlobal: ListGlobalHandle;
  36.                                     box: rect;{including the scroll bars}
  37.                                     cols, rows: integer);
  38.     procedure DisposeListGlobal (ListGlobal: ListGlobalHandle);
  39.     procedure HandleListKey (ListGlobal: ListGlobalHandle;
  40.                                     theKeyCode: integer;
  41.                                     theChar: char;
  42.                                     Modifiers: integer);
  43.     procedure DragGrayRect (startPoint: point;
  44.                                     var dragRect: rect);
  45.  
  46.     procedure UpdateLargeTERect (ListGlobal: ListGlobalHandle);
  47.  
  48.     function LGetCellString (theCell: Cell;
  49.                                     List: ListHandle): str255;
  50.     function LGetCellNumber (theCell: Cell;
  51.                                     List: ListHandle): extended;
  52.     procedure LSetCellString (theStr: str255;
  53.                                     theCell: Cell;
  54.                                     List: ListHandle);
  55.     procedure LSetCellNumber (theNum: extended;
  56.                                     decimals, SigFigures: integer;
  57.                                     theCell: Cell;
  58.                                     List: ListHandle);
  59.  
  60.     procedure SetUpCell (where: point;
  61.                                     ListGlobal: ListGlobalHandle);
  62.     procedure SetUpCell2 (theCell: cell;
  63.                                     ListGlobal: ListGlobalHandle);
  64.     procedure DisposeCell (ListGlobal: ListGlobalHandle);
  65.     procedure ClearListSelection (ListGlobal: ListGlobalHandle);
  66.  
  67.     procedure InsertRow (ListGlobal: ListGlobalHandle);
  68.     procedure AppendRow (ListGlobal: ListGlobalHandle);
  69.     procedure DeleteRow (ListGlobal: ListGlobalHandle);
  70.  
  71. implementation
  72. {*********************************************}
  73.     procedure MoveTERect (ListGlobal: ListGlobalHandle;
  74.                                     where: point);
  75.         var
  76.             newTERect: rect;
  77.             theText: handle;
  78.             error: boolean;
  79.     begin
  80.         newTERect := ListGlobal^^.TERect;
  81.         DragGrayRect(where, newTERect);
  82. {now, move the TERect}
  83.         theText := handle(TEGetText(ListGlobal^^.hTE));
  84.         myHandToHand(theText, error);
  85.         TEDispose(ListGlobal^^.hTE);
  86.         ListGlobal^^.hTE := TENew(newTERect, newTERect);
  87.         TESetText(theText^, gethandlesize(theText), ListGlobal^^.hTE);
  88.         DisposHandle(theText);
  89. {update the list hidden by the old rect}
  90.         UpdateLargeTERect(ListGlobal);
  91. {redraw any obscured controls}
  92.         DrawControls(ListGlobal^^.window);
  93. {draw the box and the text}
  94.         ListGlobal^^.TERect := newTERect;
  95.         EraseRect(ListGlobal^^.TERect);
  96.         InsetRect(ListGlobal^^.TERect, -1, -1);
  97.         FrameRect(ListGlobal^^.TERect);
  98.         InsetRect(ListGlobal^^.TERect, 1, 1);
  99.         TEAutoView(true, ListGlobal^^.hTE);
  100.         TEActivate(ListGlobal^^.hTE);
  101.         TEUpdate(ListGlobal^^.TERect, ListGlobal^^.hTE);
  102.     end;
  103. {*********************************************}
  104.     procedure CutCopyClearList (ListGlobal: ListGlobalHandle;
  105.                                     whichKey: integer);
  106.         var
  107.             error: boolean;
  108.             theText: handle;
  109.             theCell: Cell;
  110.             ClipOffset, ClipResult: longint;
  111.             lastRow: integer;
  112.             done: boolean;
  113.             err: OSErr;
  114.     begin
  115.         error := false;
  116.         DisposeCell(ListGlobal);
  117.         LSetSelect(true, ListGlobal^^.selCell, ListGlobal^^.List);
  118.         theText := mynewhandle(0, error);
  119.         SetPt(theCell, 0, 0);
  120.         lastRow := 10000;
  121.         done := true;
  122.         while done and LGetSelect(true, theCell, ListGlobal^^.List) do
  123.             begin
  124.                 if theCell.v > lastRow then
  125.                     AppendString(theText, CR, error);
  126.                 if theCell.v = lastRow then
  127.                     AppendString(theText, tab, error);
  128.                 AppendString(theText, LGetCellString(theCell, ListGlobal^^.List), error);
  129.                 case whichKey of
  130.                     xKey, dummyClearKey: 
  131.                         LClrCell(theCell, ListGlobal^^.List);
  132.                 end;{case}
  133.                 lastRow := theCell.v;
  134.                 done := LNextCell(true, true, theCell, ListGlobal^^.List);
  135.             end;
  136.         if not (whichKey = dummyClearKey) then
  137.             begin
  138.                 err := ZeroScrap;
  139.                 err := PutScrap(gethandlesize(theText), 'TEXT', theText^);
  140.             end;
  141.         DisposHandle(theText);
  142.         SetUpCell2(ListGlobal^^.selCell, ListGlobal);
  143.         TESetSelect(0, 0, ListGlobal^^.hTE);
  144.     end;
  145. {*********************************************}
  146.     procedure PasteList (ListGlobal: ListGlobalHandle;
  147.                                     OptionPressed: boolean);
  148.         var
  149.             error: boolean;
  150.             theText: CharsHandle;
  151.             ClipOffset, ClipResult, len, i: longint;
  152.             firstCell, theCell: Cell;
  153.     begin{paste}
  154.         error := false;
  155.         DisposeCell(ListGlobal);
  156.         theText := CharsHandle(mynewhandle(0, error));
  157.         ClipOffset := 0;
  158.         ClipResult := GetScrap(handle(theText), 'TEXT', ClipOffset);
  159.         firstCell := ListGlobal^^.selCell;
  160.         theCell := firstCell;
  161.         len := gethandlesize(handle(theText));
  162.         if len > 0 then
  163.             LClrCell(theCell, ListGlobal^^.List);
  164.         for i := 0 to len - 1 do
  165.             begin
  166.                 if theText^^[i] = CR then
  167.                     begin
  168.                         theCell.h := firstCell.h;
  169.                         if OptionPressed then
  170.                             begin
  171.                                 theCell.v := theCell.v + 1;
  172.                                 if not PtInRect(theCell, ListGlobal^^.List^^.dataBounds) then
  173.                                     theCell.v := LAddRow(1, theCell.v + 1, ListGlobal^^.List);
  174.                             end
  175.                         else
  176.                             theCell.v := LAddRow(1, theCell.v + 1, ListGlobal^^.List);
  177.                         if ListGlobal^^.editable[theCell.h] then
  178.                             LClrCell(theCell, ListGlobal^^.List);
  179.                     end
  180.                 else if (theText^^[i] = tab) or (theText^^[i] = comma) then
  181.                     begin
  182.                         theCell.h := theCell.h + 1;
  183.                         if ListGlobal^^.editable[theCell.h] then
  184.                             LClrCell(theCell, ListGlobal^^.List);
  185.                     end
  186.                 else if PtInRect(theCell, ListGlobal^^.List^^.dataBounds) then
  187.                     if ListGlobal^^.editable[theCell.h] then
  188.                         LAddToCell(@theText^^[i], 1, theCell, ListGlobal^^.List);
  189.             end;
  190.         DisposHandle(handle(theText));
  191.         ClearListSelection(ListGlobal);
  192.     end;
  193. {*********************************************}
  194.     procedure HandleListKey (ListGlobal: ListGlobalHandle;
  195.                                     theKeyCode: integer;
  196.                                     theChar: char;
  197.                                     Modifiers: integer);
  198.         var
  199.             theCell: Cell;
  200.             error: boolean;
  201.             theText: handle;
  202.             LastString, theString: Str255;
  203.     begin
  204.         error := false;
  205.         if BitAnd(modifiers, CmdKey) = CmdKey then
  206.             case theKeyCode of
  207.                 xKey: 
  208.                     CutCopyClearList(ListGlobal, xKey);
  209.                 cKey: 
  210.                     CutCopyClearList(ListGlobal, cKey);
  211.                 vKey, dummyOptionPasteKey: 
  212.                     PasteList(ListGlobal, OptionKeyDown or (theKeyCode = dummyOptionPasteKey));
  213.                 dummyClearKey: 
  214.                     CutCopyClearList(ListGlobal, dummyClearKey);
  215.             end
  216.         else
  217.             begin
  218.                 case WhichCursor(theKeyCode) of
  219.                     RightCurs, TabCurs: 
  220.                         begin
  221.                             theCell := ListGlobal^^.selCell;
  222.                             theCell.h := theCell.h + 1;
  223.                             DisposeCell(ListGlobal);
  224.                             SetUpCell2(theCell, ListGlobal);
  225.                         end; {tab}
  226.                     DownCurs, Carriage: 
  227.                         begin{carriage return}
  228.                             theCell := ListGlobal^^.selCell;
  229.                             theCell.v := theCell.v + 1;
  230.                             DisposeCell(ListGlobal);
  231.                             SetupCell2(theCell, ListGlobal);
  232.                         end; {carriage return}
  233.                     LeftCurs: 
  234.                         begin{left}
  235.                             theCell := ListGlobal^^.selCell;
  236.                             theCell.h := theCell.h - 1;
  237.                             DisposeCell(ListGlobal);
  238.                             SetupCell2(theCell, ListGlobal);
  239.                         end;{left}
  240.                     UpCurs: 
  241.                         begin{up}
  242.                             theCell := ListGlobal^^.selCell;
  243.                             theCell.v := theCell.v - 1;
  244.                             DisposeCell(ListGlobal);
  245.                             SetupCell2(theCell, ListGlobal);
  246.                         end;{up}
  247.                     otherwise
  248.                         begin
  249.                             if ListGlobal^^.number[ListGlobal^^.selCell.h] then
  250.                                 begin
  251.                                     error := false;
  252.                                     theText := handle(TEGetText(ListGlobal^^.hTE));
  253.                                     handletoStr255(theText, LastString, error);
  254.                                 end;
  255.                             TEKey(theChar, ListGlobal^^.hTE);
  256.                             if ListGlobal^^.number[ListGlobal^^.selCell.h] then{check that it is a number}
  257.                                 begin
  258.                                     theText := handle(TEGetText(ListGlobal^^.hTE));
  259.                                     handletoStr255(ListGlobal^^.hTE^^.hText, theString, error);
  260.                                     if not IsNumber(theString, ListGlobal^^.integer[ListGlobal^^.selCell.h]) then
  261.                                         begin
  262.                                             sysbeep(60);
  263.                                             TESetSelect(0, 32000, ListGlobal^^.hTE);
  264.                                             TEDelete(ListGlobal^^.hTE);
  265.                                             TESetText(ptrtoString(LastString), length(LastString), ListGlobal^^.hTE);
  266.                                             TEUpdate(ListGlobal^^.TErect, ListGlobal^^.hTE);
  267.                                         end;
  268.                                 end;
  269.                         end;
  270.                 end;
  271.             end;
  272.     end;
  273. {*********************************************}
  274.     function ListFilterProc (Dlg: DialogPtr;
  275.                                     var theEvent: EventRecord;
  276.                                     var ItemHit: integer): boolean;
  277.         type
  278.             FourChars = packed record
  279.                     case integer of
  280.                         0: (
  281.                                 one, two, three, four: char
  282.                         );
  283.                         1: (
  284.                                 b1, b2, b3, b4: byte
  285.                         );
  286.                 end;
  287.         var
  288.             where: point;
  289.             ListGlobal: ListGlobalHandle;
  290.             theCell: cell;
  291.             error, doubleClick: boolean;
  292.             theChar: char;
  293.             theKeyCode: byte;
  294.             ignore: boolean;
  295.  
  296.             theItem, itemType: integer;
  297.             item: handle;
  298.             box: rect;
  299.     begin
  300.         ListFilterProc := false;
  301.         where := theEvent.where;
  302.         GlobalToLocal(where);
  303.         ListGlobal := ListGlobalHandle(WindowPeek(Dlg)^.refCon);
  304.  
  305. {check if the user is terminating the dialog with the Enter key}
  306.         if theEvent.what = KeyDown then
  307.             begin{enter key}
  308.                 theChar := FourChars(theEvent.message).four;
  309.                 theKeyCode := FourChars(theEvent.message).b3;
  310.                 if theKeyCode = EnterKey then
  311.                     begin
  312.                         ListFilterProc := true;
  313.                         itemHit := 1;
  314.                     end;
  315.             end;
  316.  
  317.         if ListGlobal^^.TEExists then
  318.             begin{TEExists}
  319.                 TEIdle(ListGlobal^^.hTE);
  320.                 ListFilterProc := true;
  321.                 itemHit := ListGlobal^^.nListItem;
  322.                 case theEvent.what of
  323.                     mouseDown: 
  324.                         if PtInRect(where, ListGlobal^^.TErect) then
  325.                             begin{it is a TE event}
  326.                                 if (theEvent.modifiers = OptionKey) and ListGlobal^^.largeTErect then
  327.                                     MoveTERect(ListGlobal, where)
  328.                                 else{just click in the TE rect}
  329.                                     TEClick(where, (theEvent.modifiers = ShiftKey), ListGlobal^^.hTE);
  330.                             end{it is a TE event}
  331.                         else if PtInRect(where, ListGlobal^^.box) then
  332.                             begin{check other cells}
  333.                                 DisposeCell(ListGlobal);
  334. {check if another cell was clicked in}
  335.                                 ignore := ListFilterProc(Dlg, theEvent, itemHit);
  336.                             end
  337.                         else
  338.                             begin{not a list event}
  339. {check if the user clicked in a EditText item, if so, we must eliminate our insertion point}
  340.                                 theItem := FindDItem(Dlg, where) + 1;{FindDItem is zero based}
  341.                                 if theItem > 0 then
  342.                                     begin
  343.                                         GetDItem(Dlg, theItem, itemType, item, box);
  344.                                         if itemType = editText then
  345.                                             DisposeCell(ListGlobal);
  346.                                     end;
  347.                                 ListFilterProc := false;
  348.                             end;{not a list event}
  349.  
  350.                     KeyDown: 
  351.                         HandleListKey(ListGlobal, theKeyCode, theChar, theEvent.modifiers);
  352.  
  353.                 end;{case}
  354.             end{TEExists}
  355. {now process events when no TE record exists}
  356.         else if (theEvent.what = mouseDown) and PtInRect(where, ListGlobal^^.box) then
  357.             begin
  358.                 ListFilterProc := true;
  359.                 itemHit := ListGlobal^^.nListItem;
  360.                 if theEvent.modifiers <> ShiftKey then
  361.                     ClearListSelection(ListGlobal);{reselect the original cell}
  362.                 ListGlobal^^.doubleClick := LClick(where, theEvent.modifiers, ListGlobal^^.List);
  363.                 GetMouse(where);
  364.                 theCell.h := 0;
  365.                 theCell.v := 0;
  366. {The following is a fancy way of determining whether a single cell or a group of cells were selected}
  367.                 if LGetSelect(true, theCell, ListGlobal^^.List) then
  368.                     begin
  369.                         if (not LNextCell(true, true, theCell, ListGlobal^^.List)) or (not LGetSelect(true, theCell, ListGlobal^^.List)) then
  370.                             begin{only a single cell was selected}
  371.                                 doubleClick := LClick(where, theEvent.modifiers, ListGlobal^^.List);
  372.                                 GetMouse(where);
  373.                                 SetupCell(where, ListGlobal);
  374.                                 ListGlobal^^.multiple := false;
  375.                             end
  376.                         else
  377.                             begin{multiple selection}
  378.                                 theCell.h := 0;
  379.                                 theCell.v := 0;
  380.                                 if LGetSelect(true, theCell, ListGlobal^^.List) then
  381.                                     begin
  382.                                         SetUpCell2(theCell, ListGlobal);
  383.                                         TESetSelect(0, 0, ListGlobal^^.hTE);
  384.                                         ListGlobal^^.multiple := true;
  385.                                     end;
  386.                             end;{multiple selection}
  387.                     end;
  388.             end
  389.     end;
  390. {*************************************************}
  391.     procedure ListActionProc (Dlg: DialogPtr;
  392.                                     itemNo: integer);
  393.         var
  394.             itemType: integer;
  395.             item: handle;
  396.             box: rect;
  397.             boxRgn: RgnHandle;
  398.             ListGlobal: ListGlobalHandle;
  399.     begin
  400.         GetDItem(Dlg, itemNo, itemType, item, box);
  401.         boxRgn := NewRgn;
  402.         RectRgn(boxRgn, Dlg^.portRect);
  403.         longint(ListGlobal) := WindowPeek(Dlg)^.RefCon;
  404.         LUpdate(boxRgn, ListGlobal^^.List);
  405.         DisposeRgn(boxRgn);
  406.  
  407.         box := ListGlobal^^.List^^.rView;
  408.         InsetRect(box, -1, -1);
  409.         FrameRect(box);
  410.     end;
  411. {*************************************************}
  412.     procedure SetUpListItem (Dlg: DialogPtr;
  413.                                     nListItem: integer;
  414.                                     var ListGlobal: ListGlobalHandle;
  415.                                     cols, rows: integer);
  416.         var
  417.             error: boolean;
  418.             itemType: integer;
  419.             item: handle;
  420.             box: rect;
  421.     begin
  422.         error := false;
  423.         GetDItem(Dlg, nListItem, itemType, item, box);
  424.         SetDItem(Dlg, nListItem, itemType, handle(@ListActionProc), box);
  425.         ShowWindow(Dlg);
  426.  
  427.         SetUpList(Dlg, ListGlobal, box, cols, rows);
  428.         ListGlobal^^.nListItem := nListItem;
  429.     end;
  430. {*************************************}
  431.     procedure SetUpList;
  432.         var
  433.             error: boolean;
  434.             rView, dataBounds: rect;
  435.             cSize: point;
  436.             i: integer;
  437.             theFont: fontInfo;
  438.             nRows: integer;
  439.     begin
  440.         error := false;
  441.         ListGlobal := ListGlobalHandle(myNewHandle(sizeof(ListGlobalType), error));
  442.         WindowPeek(w)^.RefCon := longint(ListGlobal);
  443.         ListGlobal^^.window := w;
  444.         ListGlobal^^.box := box;
  445.         ListGlobal^^.TEExists := false;
  446.         ListGlobal^^.doubleClick := false;
  447.         GetFontInfo(theFont);
  448.         rView := box;
  449.         rView.right := rView.right - 15;
  450.         SetRect(dataBounds, 0, 0, cols, rows);
  451.         cSize.h := (rView.right - rView.left) div dataBounds.right;
  452.         nRows := ((rView.bottom - rView.top) div (theFont.ascent + theFont.descent));
  453.         cSize.v := (rView.bottom - rView.top) div nRows;
  454.         rView.bottom := rView.top + cSize.v * nRows;
  455.         ListGlobal^^.List := LNew(rView, dataBounds, cSize, 0, w, true, false, false, true);
  456.         InsetRect(rView, -1, -1);
  457.         FrameRect(rView);
  458.         for i := 0 to cols - 1 do
  459.             begin
  460.                 ListGlobal^^.editable[i] := true;
  461.                 ListGlobal^^.number[i] := true;
  462.                 ListGlobal^^.integer[i] := false;
  463.             end;
  464.     end;
  465. {*************************************************}
  466.     procedure DisposeListGlobal (ListGlobal: ListGlobalHandle);
  467.     begin
  468.         DisposeCell(ListGlobal);
  469.         LDispose(ListGlobal^^.List);
  470.         DisposHandle(handle(ListGlobal));
  471.     end;
  472. {*************************************************}
  473.     procedure UpdateLargeTERect;
  474.         var
  475.             UpdateRgn: RgnHandle;
  476.             rView: rect;
  477.     begin
  478.         UpdateRgn := NewRgn;
  479.         InsetRect(ListGlobal^^.TERect, -1, -1);
  480.         EraseRect(ListGlobal^^.TERect);
  481.         RectRgn(UpdateRgn, ListGlobal^^.TERect);
  482.         LUpdate(UpdateRgn, ListGlobal^^.List);
  483.         DisposeRgn(UpdateRgn);
  484.         rView := ListGlobal^^.List^^.rView;
  485.         InsetRect(rView, -1, -1);
  486.         FrameRect(rView);
  487.     end;
  488. {*************************************************}
  489.     procedure DragGrayRect;
  490.         var
  491.             SavePen: PenState;
  492.             newMouse, oldMouse: point;
  493.     begin
  494.         GetPenState(SavePen);
  495.         PenMode(PatXor);{redrawing the same rect causes it to be erased}
  496.         PenPat(gray);
  497.  
  498.         oldMouse := startPoint;
  499.         FrameRect(dragRect);
  500.         repeat{check to see if it is torn off}
  501.             GetMouse(newMouse);
  502.             if not EqualPt(newMouse, oldMouse) then
  503.                 begin
  504.                     FrameRect(dragRect);{erase}
  505.                     OffsetRect(dragRect, newMouse.h - oldMouse.h, newMouse.v - oldMouse.v);
  506.                     oldMouse := newMouse;
  507.                     FrameRect(dragRect);{redraw}
  508.                 end;
  509.         until not Button;{check to see if it is torn off}
  510.         FrameRect(dragRect);
  511.  
  512.         SetPenState(SavePen);
  513.     end;
  514. {*************************************************}
  515.     procedure VerifyCell (var theCell: Cell;
  516.                                     theList: ListHandle);
  517.     begin
  518.         if theCell.h < 0 then
  519.             begin
  520.                 theCell.h := theList^^.dataBounds.right - 1;
  521.                 theCell.v := theCell.v - 1;
  522.                 if theCell.v < 0 then
  523.                     theCell.v := theList^^.dataBounds.bottom - 1;
  524.             end;
  525.         if theCell.v < 0 then
  526.             begin
  527.                 theCell.v := theList^^.dataBounds.bottom - 1;
  528.                 theCell.h := theCell.h - 1;
  529.                 if theCell.h < 0 then
  530.                     theCell.h := theList^^.dataBounds.right - 1;
  531.             end;
  532.         if theCell.h >= theList^^.dataBounds.right then
  533.             begin
  534.                 theCell.h := 0;
  535.                 theCell.v := theCell.v + 1;
  536.                 if theCell.v >= theList^^.dataBounds.bottom then
  537.                     theCell.v := 0;
  538.             end;
  539.         if theCell.v >= theList^^.dataBounds.bottom then
  540.             begin
  541.                 theCell.v := 0;
  542.                 theCell.h := theCell.h + 1;
  543.                 if theCell.h >= theList^^.dataBounds.right then
  544.                     theCell.h := 0;
  545.             end;
  546.     end;
  547. {***********************************************}
  548.     procedure LInitRow (ListGlobal: ListGlobalHandle;
  549.                                     row: integer);
  550.         var
  551.             i: integer;
  552.             theCell: Cell;
  553.     begin
  554.         theCell.v := row;
  555.         theCell.h := 0;
  556.  
  557.         if not ListGlobal^^.number[0] then
  558.             LSetCellString('blank', theCell, ListGlobal^^.List);
  559.  
  560.         for i := 1 to ListGlobal^^.List^^.dataBounds.right do
  561.             if ListGlobal^^.number[i - 1] then
  562.                 begin
  563.                     theCell.h := i - 1;
  564.                     LSetCellNumber(0, 0, 0, theCell, ListGlobal^^.List);
  565.                 end;
  566.         theCell.h := 0;
  567.         SetupCell2(theCell, ListGlobal);
  568.     end;
  569. {***********************************************}
  570.     procedure InsertRow;
  571.         var
  572.             row: integer;
  573.     begin
  574.         if PtInRect(ListGlobal^^.selCell, ListGlobal^^.List^^.dataBounds) then
  575.             begin
  576.                 DisposeCell(ListGlobal);
  577.                 row := ListGlobal^^.selCell.v;
  578.                 row := LAddRow(1, row, ListGlobal^^.List);
  579.                 LInitRow(ListGlobal, row);
  580.             end;
  581.     end;
  582. {*************************************************}
  583.     procedure AppendRow;
  584.         var
  585.             row: integer;
  586.     begin
  587.         DisposeCell(ListGlobal);
  588.         row := LAddRow(1, 10000, ListGlobal^^.List);
  589.         LInitRow(ListGlobal, row);
  590.     end;
  591. {*************************************************}
  592.     procedure DeleteRow;
  593.         var
  594.             theCell: cell;
  595.     begin
  596.         if PtInRect(ListGlobal^^.selCell, ListGlobal^^.List^^.dataBounds) then
  597.             begin
  598.                 theCell := ListGlobal^^.selCell;
  599.                 DisposeCell(ListGlobal);
  600.                 LDelRow(1, theCell.v, ListGlobal^^.List);
  601.                 if theCell.v > 0 then
  602.                     theCell.v := theCell.v - 1;
  603.                 if ListGlobal^^.List^^.databounds.bottom > 0 then
  604.                     SetupCell2(theCell, ListGlobal);
  605.             end;
  606.     end;
  607. {*************************************************}
  608.     procedure SetUpCell2;
  609.         var
  610.             cellRect: rect;
  611.     begin
  612.         VerifyCell(theCell, ListGlobal^^.List);
  613.         LSetSelect(true, theCell, ListGlobal^^.List);
  614.         LAutoScroll(ListGlobal^^.List);
  615.  
  616.         LRect(cellRect, theCell, ListGlobal^^.List);
  617.         SetUpCell(cellRect.topLeft, ListGlobal);
  618.         if ListGlobal^^.TEExists then
  619.             TESetSelect(0, 32000, ListGlobal^^.hTE);
  620.     end;
  621. {*************************************************}
  622.     procedure SetUpCell;
  623.         var
  624.             theData: ptr;
  625.             dataLen: integer;
  626.             ignore: boolean;
  627.             width: integer;
  628.     begin
  629.         ignore := LClick(where, 0, ListGlobal^^.List);
  630.         ListGlobal^^.selCell := LLastClick(ListGlobal^^.List);
  631.         if PtInRect(ListGlobal^^.selCell, ListGlobal^^.List^^.dataBounds) and ListGlobal^^.editable[ListGlobal^^.selCell.h] then
  632.             begin
  633.                 ListGlobal^^.TEExists := true;
  634.                 LSetSelect(true, ListGlobal^^.selCell, ListGlobal^^.List);
  635.                 LRect(ListGlobal^^.TERect, ListGlobal^^.selCell, ListGlobal^^.List);
  636.                 ignore := LClick(ListGlobal^^.TERect.topLeft, 0, ListGlobal^^.List);{clear the old cell}
  637.                 theData := NewPtr(255);
  638.                 dataLen := 255;
  639.                 LGetCell(theData, dataLen, ListGlobal^^.selCell, ListGlobal^^.List);
  640.                 width := TextWidth(theData, 0, dataLen);
  641. {check if the text is too wide for the cell}
  642.                 if width > (ListGlobal^^.TERect.right - ListGlobal^^.TERect.left) then
  643.                     begin
  644.                         ListGlobal^^.TERect.right := ListGlobal^^.TERect.left + 3 * (ListGlobal^^.TERect.right - ListGlobal^^.TERect.left);
  645.                         ListGlobal^^.TERect.bottom := ListGlobal^^.TERect.top + 2 * (ListGlobal^^.TERect.bottom - ListGlobal^^.TERect.top);
  646. {CheckOnScreen(ListGlobal^^.TERect);}
  647.                         InsetRect(ListGlobal^^.TERect, -1, -1);
  648.                         FrameRect(ListGlobal^^.TERect);
  649.                         InsetRect(ListGlobal^^.TERect, 1, 1);
  650.                         ListGlobal^^.largeTERect := true;
  651.                     end
  652.                 else
  653.                     ListGlobal^^.largeTERect := false;
  654.  
  655.                 ListGlobal^^.hTE := TENew(ListGlobal^^.TERect, ListGlobal^^.TERect);
  656.                 TEAutoView(true, ListGlobal^^.hTE);
  657.                 TESetText(theData, dataLen, ListGlobal^^.hTE);
  658.                 DisposPtr(theData);
  659.                 TEActivate(ListGlobal^^.hTE);
  660.                 EraseRect(ListGlobal^^.TERect);
  661.                 TEUpdate(ListGlobal^^.TERect, ListGlobal^^.hTE);
  662.  
  663.                 TEClick(where, false, ListGlobal^^.hTE)
  664.             end;
  665.     end;
  666. {*************************************************}
  667.     procedure DisposeCell;
  668.         var
  669.             error: boolean;
  670.             theString: str255;
  671.             theText: handle;
  672.     begin
  673.         if ListGlobal^^.TEExists then
  674.             begin
  675.                 ListGlobal^^.TEExists := false;
  676.                 error := false;
  677.                 theText := handle(TEGetText(ListGlobal^^.hTE));{does this handle need to be disposed??}
  678.                 HandleToStr255(theText, theString, error);
  679.                 TEDispose(ListGlobal^^.hTE);
  680.                 LSetCellString(theString, ListGlobal^^.selCell, ListGlobal^^.List);
  681.                 LSetSelect(false, ListGlobal^^.selCell, ListGlobal^^.List);
  682.                 if ListGlobal^^.largeTERect then
  683.                     UpdateLargeTERect(ListGlobal);
  684.             end;
  685.     end;
  686. {***********************************}
  687.     procedure ClearListSelection (ListGlobal: ListGlobalHandle);
  688.         var
  689.             theCell: Cell;
  690.     begin
  691.         if ListGlobal^^.multiple then
  692.             begin
  693.                 SetPt(theCell, 0, 0);
  694.                 while LGetSelect(true, theCell, ListGlobal^^.List) do
  695.                     LSetSelect(false, theCell, ListGlobal^^.List);
  696.             end;
  697.     end;
  698. {***********************************}
  699.     function LGetCellNumber;
  700.     begin
  701.         LGetCellNumber := stringToReal(LGetCellString(theCell, List));
  702.     end;
  703. {*************************************************}
  704.     function LGetCellString;
  705.         var
  706.             theLen: integer;
  707.             thePtr: ptr;
  708.             theStr: str255;
  709.     begin
  710.         theLen := 255;
  711.         thePtr := NewPtr(theLen);
  712.         LGetCell(thePtr, theLen, theCell, List);
  713.         theStr[0] := char(theLen);
  714.         blockMove(thePtr, ptr(longint(@theStr) + 1), theLen);
  715.         LGetCellString := theStr;
  716.         DisposPtr(thePtr);
  717.     end;
  718. {*************************************************}
  719.     procedure LSetCellString (theStr: str255;
  720.                                     theCell: Cell;
  721.                                     List: ListHandle);
  722.     begin
  723.         LSetCell(ptr(longint(@theStr) + 1), length(theStr), theCell, List);
  724.     end;
  725. {*************************************************}
  726.     procedure LSetCellNumber (theNum: extended;
  727.                                     decimals, SigFigures: integer;
  728.                                     theCell: Cell;
  729.                                     List: ListHandle);
  730.     begin
  731.         if SigFigures > 0 then
  732.             LSetCellString(RealToString(theNum, SigFigures), theCell, List)
  733.         else
  734.             LSetCellString(RealToFixed(theNum, decimals), theCell, List);
  735.     end;
  736. {***********************************************}
  737. end.